package com.aiti.lulian.service.impl;

import cn.hutool.core.util.StrUtil;
import com.aiti.base.core.base.service.iml.BaseSerivceImpl;
import com.aiti.base.core.constant.MessageCodeConstant;
import com.aiti.base.core.utils.message.Message;
import com.aiti.lulian.dto.CardVisitorRecordDto;
import com.aiti.lulian.entity.CardOperationLog;
import com.aiti.lulian.entity.CardVisitorRecord;
import com.aiti.lulian.entity.LuLianEnterpriseUser;
import com.aiti.lulian.entity.newCard.CardBaseInfo;
import com.aiti.lulian.entity.newCard.CardMessage;
import com.aiti.lulian.feign.CloudShowManagerSubService;
import com.aiti.lulian.mapper.CardOperationLogMapper;
import com.aiti.lulian.mapper.CardVisitorRecordMapper;
import com.aiti.lulian.mapper.newCard.CardMessageMapper;
import com.aiti.lulian.mapper.newCard.CardPersonalBaseInfoMapper;
import com.aiti.lulian.service.ICardVisitorRecordService;
import com.aiti.lulian.service.ILuLianEnterpriseUserService;
import com.aiti.lulian.vo.CardVisitorRecordVo;
import com.aiti.lulian.vo.UserIdAndUserName;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class CardVisitorRecordServiceImpl extends BaseSerivceImpl<CardVisitorRecordMapper, CardVisitorRecord> implements ICardVisitorRecordService {

    private final CardVisitorRecordMapper cardVisitorRecordMapper;

    private final CloudShowManagerSubService cloudShowManagerSubService;

    private final ILuLianEnterpriseUserService luLianEnterpriseUserService;

    private final CardOperationLogMapper cardOperationLogMapper;

    private final CardPersonalBaseInfoMapper cardPersonalBaseInfoMapper;

    private final CardMessageMapper cardMessageMapper;

    private Lock lock = new ReentrantLock();

    private final String GET_WX_USER_OPENID = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public int insertOrUpdateVisitorRecord(String userId, String currentUserId, String source) {
        if (StrUtil.equals(currentUserId, "undefined")) {
            return 0;
        } else {
            LambdaQueryWrapper<CardVisitorRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CardVisitorRecord::getUserId, userId);
            queryWrapper.eq(CardVisitorRecord::getVisitorId, currentUserId);
            List<CardVisitorRecord> list = cardVisitorRecordMapper.selectList(queryWrapper);
            if (list == null || list.size() == 0) {
                //新增访客记录
                CardVisitorRecord build = CardVisitorRecord.builder()
                        .visitorId(currentUserId)
                        .userId(userId)
                        .source(source)
                        .baseCreateTime(new Date())
                        .baseUpdateTime(new Date())
                        .build();
                return cardVisitorRecordMapper.insert(build);
            } else if (list.size() > 1) {
                log.error("user_id 为【{}】，visitor_id 为【{}】的访客记录存在重复数据！", userId, currentUserId);
                throw new RuntimeException("访客记录异常！");
            } else {
                //更新访客记录
                LambdaUpdateWrapper<CardVisitorRecord> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(CardVisitorRecord::getUserId, userId);
                updateWrapper.eq(CardVisitorRecord::getVisitorId, currentUserId);
                //访问次数 + 1
                updateWrapper.set(CardVisitorRecord::getCount, list.get(0).getCount() + 1);
                updateWrapper.set(CardVisitorRecord::getBaseUpdateTime, new Date());
                updateWrapper.set(CardVisitorRecord::getSource, source);
                return cardVisitorRecordMapper.update(null, updateWrapper);
            }
        }
    }

    @Override
    public void insertOrUpdateVisitorRecordNew(String userId, String visitorId, String cardId, String visitorCardId, String source) {
        if (StrUtil.equals(visitorId, "undefined") || StrUtil.equals(visitorCardId, "undefined")) {
            log.error("undefined：获取当前访问人用户ID或名片ID失败");
        } else {
            List<CardVisitorRecord> list = cardVisitorRecordMapper.selectList(new LambdaQueryWrapper<CardVisitorRecord>().eq(CardVisitorRecord::getCardId, cardId).eq(CardVisitorRecord::getVisitorCardId, visitorCardId));
            if (list.size() == 0) {
                // 新增访客记录
                CardVisitorRecord build = CardVisitorRecord.builder()
                        .visitorId(visitorId)
                        .userId(userId)
                        .source(source)
                        .cardId(cardId)
                        .visitorCardId(visitorCardId)
                        .userId(userId)
                        .baseCreateTime(new Date())
                        .baseUpdateTime(new Date())
                        .build();
                // 查看是否已存在相反的访客记录，若存在则同步交换状态
                List<CardVisitorRecord> oppositeList = cardVisitorRecordMapper.selectList(new LambdaQueryWrapper<CardVisitorRecord>().eq(CardVisitorRecord::getCardId, visitorCardId).eq(CardVisitorRecord::getVisitorCardId, cardId).eq(CardVisitorRecord::getUserId, visitorId).eq(CardVisitorRecord::getVisitorId, userId));
                if (!oppositeList.isEmpty()) {
                    build.setExchangeStatus(oppositeList.get(0).getExchangeStatus());
                }
                cardVisitorRecordMapper.insert(build);
            } else if (list.size() > 1) {
                log.error("card_id【{}】visitor_card_id【{}】的访客记录存在重复数据！", cardId, visitorCardId);
            } else {
                // 更新访客记录 访问次数 + 1
                this.update(new LambdaUpdateWrapper<CardVisitorRecord>().eq(CardVisitorRecord::getCardId, cardId).eq(CardVisitorRecord::getVisitorCardId, visitorCardId)
                        .set(CardVisitorRecord::getCount, list.get(0).getCount() + 1)
                        .set(CardVisitorRecord::getBaseUpdateTime, new Date())
                        .set(CardVisitorRecord::getSource, source));
            }
        }
    }

    @Override
    public List<CardVisitorRecordVo> queryMyVisitorList(String cardId) {
        List<CardVisitorRecordVo> cardVisitorRecordVos = cardVisitorRecordMapper.selectCardVisitorRecord(cardId);
        if (cardVisitorRecordVos == null) {
            return new ArrayList<>();
        }
        return cardVisitorRecordVos;
    }

    @Override
    public List<CardVisitorRecordVo> queryVisitorList(String userId, String enterpriseId, String realname, String enterpriseName, String visitedRealname, String condition, Page<CardVisitorRecord> page) {
        //声明所需变量
        //用于接收受访人userId集
        List<String> userIdList = new ArrayList<>(Arrays.asList(userId));
        String scope = null;
        //获取当前用户的权限
        Message userAccessScopeMessage = cloudShowManagerSubService.queryUserAccessScope(userId);
        if (userAccessScopeMessage == null) {
            throw new RuntimeException("获取用户访问权限失败");
        } else if (! userAccessScopeMessage.getCode().equals(MessageCodeConstant.MSG_SUCCESS_CODE)) {
            throw new RuntimeException("查询用户访问权限失败");
        } else {
            scope = (String) userAccessScopeMessage.getObj();
        }
        //判断该用户是否为企业管理员
        boolean enterpriseAdmin = StrUtil.equals(scope, "4");
        if(enterpriseAdmin){
            LambdaQueryWrapper<LuLianEnterpriseUser> lianEnterpriseUserQueryWrapper = new LambdaQueryWrapper<>();
            lianEnterpriseUserQueryWrapper.eq(LuLianEnterpriseUser::getEnterpriseId, enterpriseId);
            List<LuLianEnterpriseUser> luLianEnterpriseUserList = luLianEnterpriseUserService.list(lianEnterpriseUserQueryWrapper);
            if (luLianEnterpriseUserList != null && luLianEnterpriseUserList.size() > 0)
                userIdList = luLianEnterpriseUserList.stream().map(i -> i.getUserId()).collect(Collectors.toList());
        } else {
            //判断该用户是否为部门负责人
            Message userInfoMessage = cloudShowManagerSubService.getUserInfo(userId);
            if (userInfoMessage == null) {
                throw new RuntimeException("获取用户信息失败");
            } else if (! userInfoMessage.getCode().equals(MessageCodeConstant.MSG_SUCCESS_CODE)) {
                throw new RuntimeException("查询用户信息失败");
            } else {
                Object obj = userInfoMessage.getObj();
                if (obj == null) {
                    throw new RuntimeException("查询用户为空");
                }
                ObjectMapper mapper = new ObjectMapper();
                Map userInfoMap = mapper.convertValue(obj, Map.class);
                String deptPermission = (String) userInfoMap.get("deptPermission");
                String deptId = (String) userInfoMap.get("deptId");

                //若为部门负责人，则获取其部门下所有成员ID集
                if (StrUtil.equals(deptPermission, "1")) {
                    Message getUserIdsMessage = cloudShowManagerSubService.getUserIdsByDeptId(deptId);
                    if (getUserIdsMessage == null) {
                        throw new RuntimeException("获取部门成员失败");
                    } else if (! getUserIdsMessage.getCode().equals(MessageCodeConstant.MSG_SUCCESS_CODE)) {
                        throw new RuntimeException("查询部门成员失败");
                    } else {
                        List<String> userIds = (List<String>) getUserIdsMessage.getObj();
                        if (userIds == null) {
                            throw new RuntimeException("查询部门成员为空");
                        }
                        userIdList = userIds;
                    }
                } else {
                    //普通员工
                }
            }
        }

        List<CardVisitorRecordVo> cardVisitorRecordVos = cardVisitorRecordMapper.selectCardVisitorRecordByUserIds(userIdList, realname, enterpriseName, visitedRealname, condition, page, scope);
            if (cardVisitorRecordVos != null && cardVisitorRecordVos.size() > 0) {
                return cardVisitorRecordVos;
            }
            return new ArrayList<>();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Message editVisitorRemarks(CardVisitorRecordDto dto) {
        CardVisitorRecord visitorRecord = new CardVisitorRecord();
        BeanUtils.copyProperties(dto, visitorRecord);
        String currentUserId = dto.getCurrentUserId();
        String baseId = dto.getBaseId();
        CardVisitorRecord byId = this.getById(baseId);
        if (byId != null) {
            if (StrUtil.isNotBlank(byId.getRemarkCreator()) || byId.getRemarkCreateTime() != null) {
                //代表更新备注
                visitorRecord.setRemarkUpdateBy(currentUserId);
                visitorRecord.setRemarkUpdateTime(new Date());
            } else {
                //代表创建备注
                visitorRecord.setRemarkCreator(currentUserId);
                visitorRecord.setRemarkCreateTime(new Date());
            }
            this.updateById(visitorRecord);
        } else {
            CardOperationLog cardOperationLog = cardOperationLogMapper.selectById(baseId);
            if (cardOperationLog != null) {
                LambdaUpdateWrapper<CardOperationLog> updateWrapper = new LambdaUpdateWrapper<CardOperationLog>().eq(CardOperationLog::getBaseId, baseId)
                        .set(CardOperationLog::getRealnameRemarks, dto.getRealnameRemarks())
                        .set(CardOperationLog::getEnterpriseNameRemarks, dto.getEnterpriseNameRemarks())
                        .set(CardOperationLog::getWeixinRemarks, dto.getWeixinRemarks())
                        .set(CardOperationLog::getPositionRemarks, dto.getPositionRemarks())
                        .set(CardOperationLog::getPhoneRemarks, dto.getPhoneRemarks());
                if (StrUtil.isNotBlank(cardOperationLog.getRemarkCreator()) || cardOperationLog.getRemarkCreateTime() != null) {
                    //代表更新备注
                    updateWrapper.set(CardOperationLog::getRemarkUpdateBy, currentUserId);
                    updateWrapper.set(CardOperationLog::getRemarkUpdateTime, new Date());
                } else {
                    //代表创建备注
                    updateWrapper.set(CardOperationLog::getRemarkCreator, currentUserId);
                    updateWrapper.set(CardOperationLog::getRemarkCreateTime, new Date());
                }
                cardOperationLogMapper.update(null, updateWrapper);
            }
        }

        return Message.success();
    }

    @Override
    public CardVisitorRecordVo queryVisitorDetail(String baseId) {
        CardVisitorRecordVo cardVisitorRecordVo = this.baseMapper.selectVisitorDetail(baseId);
        if (cardVisitorRecordVo == null) {
            //visitorId = "isNotLogin"的历史数据
            cardVisitorRecordVo = cardOperationLogMapper.selectVisitorDetail(baseId);
        }
        return cardVisitorRecordVo;
    }

    @Override
    public Message setContactNumber(CardVisitorRecordDto dto) {
        String findUrl = String.format(GET_WX_USER_OPENID, "wx7ca766313703d868", "ee06b7594ea4239ab55153d1bae9461c", dto.getLoginCode());
        ResponseEntity<String> forEntity = restTemplate.getForEntity(findUrl, String.class);
        if(forEntity.getStatusCode().is2xxSuccessful()) {
            String body = forEntity.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String unionid = jsonObject.getObject("unionid", String.class);
            List<CardVisitorRecord> list = this.list(new LambdaQueryWrapper<CardVisitorRecord>().eq(CardVisitorRecord::getCardId, dto.getCardId()).like(CardVisitorRecord::getVisitorCardId, unionid));
            List<CardVisitorRecord> dataList = list.stream().peek(i -> i.setContactNumber(dto.getContactNumber())).collect(Collectors.toList());
            this.updateBatchById(dataList);
            return Message.success();
        }
        log.error("设置登录但没名片访客的手机号时unionid获取失败，访客手机号为：【{}】，受访人名片ID为：【{}】", dto.getContactNumber(), dto.getCardId());
        return Message.success();
    }

    @Override
    public Message updateNotLoginRecord(CardVisitorRecordDto dto) {
        String findUrl = String.format(GET_WX_USER_OPENID, "wx7ca766313703d868", "ee06b7594ea4239ab55153d1bae9461c", dto.getLoginCode());
        ResponseEntity<String> forEntity = restTemplate.getForEntity(findUrl, String.class);
        if(forEntity.getStatusCode().is2xxSuccessful()) {
            String body = forEntity.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String unionid = jsonObject.getObject("unionid", String.class);
            List<CardVisitorRecord> list = this.list(new LambdaQueryWrapper<CardVisitorRecord>().like(CardVisitorRecord::getVisitorId, unionid));
            String visitorId = dto.getVisitorId();
            for (CardVisitorRecord cardVisitorRecord : list) {
                this.update(new LambdaUpdateWrapper<CardVisitorRecord>().eq(CardVisitorRecord::getBaseId, cardVisitorRecord.getBaseId())
                        .set(CardVisitorRecord::getVisitorId, visitorId)
                        .set(CardVisitorRecord::getRealnameRemarks, null)
                        .set(CardVisitorRecord::getEnterpriseNameRemarks, null)
                        .set(CardVisitorRecord::getWeixinRemarks, null)
                        .set(CardVisitorRecord::getPositionRemarks, null)
                        .set(CardVisitorRecord::getPhoneRemarks, null)
                        .set(CardVisitorRecord::getRemarkCreator, null)
                        .set(CardVisitorRecord::getRemarkCreateTime, null)
                        .set(CardVisitorRecord::getRemarkUpdateBy, null)
                        .set(CardVisitorRecord::getRemarkUpdateTime, null)
                        .set(CardVisitorRecord::getContactNumber, null));
            }
            return Message.success();
            }
        log.error("设置登录但没名片访客的手机号时unionid获取失败，访客手机号为：【{}】，受访人用户ID为：【{}】", dto.getContactNumber(), dto.getUserId());
        return Message.success();
    }

    @Override
    public List<CardVisitorRecordVo> queryMyVisitedList(String cardId) {
        List<CardVisitorRecordVo> cardVisitorRecordVos = cardVisitorRecordMapper.selectCardVisitedRecord(cardId);
        if (cardVisitorRecordVos == null) {
            return new ArrayList<>();
        }
        return cardVisitorRecordVos;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void visitCard(CardVisitorRecordDto dto) {
        String visitorCardId = dto.getVisitorCardId();
        String cardId = dto.getCardId();
        String visitorId = dto.getVisitorId();
        String userId = dto.getUserId();
        if (StrUtil.equals(visitorCardId, "isNotLogin") && StrUtil.isNotBlank(dto.getLoginCode())) {
            String findUrl = String.format(GET_WX_USER_OPENID, "wx7ca766313703d868", "ee06b7594ea4239ab55153d1bae9461c", dto.getLoginCode());
            ResponseEntity<String> forEntity = restTemplate.getForEntity(findUrl, String.class);
            if(forEntity.getStatusCode().is2xxSuccessful()) {
                String body = forEntity.getBody();
                JSONObject jsonObject = JSONObject.parseObject(body);
                String unionid = jsonObject.getObject("unionid", String.class);
                visitorId = "微信用户" + unionid;
                visitorCardId = "微信用户" + unionid;
            }
        }

        try {
            lock.lock();
            if (!StrUtil.equals(visitorCardId, "undefined") && !StrUtil.equals(cardId, "undefined") && !StrUtil.equals(visitorCardId, cardId)) {
                // 为后面需要获取名片信息的地方准备
                CardBaseInfo cardInfo = cardPersonalBaseInfoMapper.selectById(cardId);
                CardBaseInfo visitorCardInfo = cardPersonalBaseInfoMapper.selectById(visitorCardId);
                // Redis构建Key:当前登录人 + @ + 发名片人Id
                String viewRedisKey = "view_count:" + visitorCardId + "@" + cardId;

//                if(!redisTemplate.hasKey(viewRedisKey) || StrUtil.equals(visitorCardId, "isNotLogin")) {
                if(!redisTemplate.hasKey(viewRedisKey)) {
                    // 获取当前时间
                    LocalDateTime now = LocalDateTime.now();
                    LocalDateTime localTime = now.withHour(23).withMinute(55).withSecond(59);
                    if (now.isAfter(localTime)) {
                        // 如果当前时间过了设置的23点55分则设置第二天的23点55分
                        localTime = localTime.plusDays(1);
                    }
                    long expiryInSeconds = localTime.toEpochSecond(ZoneOffset.UTC) - now.toEpochSecond(ZoneOffset.UTC);
                    redisTemplate.opsForValue().set(viewRedisKey, "1", expiryInSeconds, TimeUnit.SECONDS);

                    // 获取当前用户的被查看名片数量
                    Long toDayCount = cardInfo.getToDayCount() == null ? 0 : cardInfo.getToDayCount();
                    Long viewCount = cardInfo.getViewCount() == null ? 0 : cardInfo.getViewCount();
                    cardInfo.setToDayCount(toDayCount + 1);
                    cardInfo.setViewCount(viewCount + 1);
                    // 修改当前用户的名片信息的访问数量
                    cardPersonalBaseInfoMapper.updateById(cardInfo);
                    // 新增或更新访客记录
                    this.insertOrUpdateVisitorRecordNew(userId, visitorId, cardId, visitorCardId, StrUtil.isNotBlank(dto.getSource()) ? dto.getSource() : "others");

                    // 新增访问日志
                    CardOperationLog cardOperationLog = CardOperationLog.builder()
                            .userId(userId)
                            .cardId(cardId)
                            .enterpriseId(cardInfo == null ? null : cardInfo.getEnterpriseId())
                            .visitorUserId(visitorId)
                            .visitorCardId(visitorCardId)
                            .visitorEnterpriseId(visitorCardInfo == null ? null : visitorCardInfo.getEnterpriseId())
                            .type("2")
                            .visitorSource(StrUtil.isNotBlank(dto.getSource()) ? dto.getSource() : "others")
                            .build();
                    cardOperationLogMapper.insert(cardOperationLog);
                }
                // 增加来访消息
                if (visitorCardId != null) {
                    cardMessageMapper.insert(CardMessage.builder()
                            .senderCardId(visitorCardId)
                            .receiverCardId(cardId)
                            .content((visitorCardInfo == null ? visitorCardId : visitorCardInfo.getName()) + "访问了您的名片")
                            .source(1)
                            .build());
                }
            }
        } finally {
            lock.unlock();
        }
    }

    @Override
    public List<UserIdAndUserName> getVisitorRecords(String userId) {
        List<CardVisitorRecord> cardVisitorRecords = cardVisitorRecordMapper.selectList(new QueryWrapper<CardVisitorRecord>().eq("user_id",userId));
        List<UserIdAndUserName> result = new ArrayList<>();
        if(cardVisitorRecords != null && !cardVisitorRecords.isEmpty()){
            List<String> userIds = cardVisitorRecords.stream().filter(item -> StringUtils.isNotBlank(item.getVisitorId())).map(CardVisitorRecord::getVisitorId).collect(Collectors.toList());
            if(userIds != null && !userIds.isEmpty()){
                Message usersInfoMessage = cloudShowManagerSubService.getUsersInfo(userIds);
                if(usersInfoMessage.getCode() == MessageCodeConstant.MSG_FAIL_CODE){
                    throw new RuntimeException("获取用户信息失败");
                }
                Map<String, Map<String, String>> messageMap = (Map<String, Map<String, String>>)usersInfoMessage.getObj();
                for(Map.Entry<String, Map<String, String>> entry : messageMap.entrySet()){
                    Map<String, String> value = entry.getValue();
                    String realName = value.get("nickname");
                    if(StringUtils.isBlank(realName)){
                        realName = value.get("realname");
                        if(StringUtils.isBlank(realName)){
                            realName = value.get("username");
                        }
                    }
                    String user_id = value.get("baseId");
                    UserIdAndUserName build = UserIdAndUserName.builder()
                            .userName(realName)
                            .userId(user_id)
                            .build();
                    result.add(build);
                }
            }
        }
        return result;
     }

    @Override
    public List<CardVisitorRecordVo> queryVisitorListBackend(CardVisitorRecordDto dto, Page<CardVisitorRecord> page) {
        return cardVisitorRecordMapper.selectVisitorListBackend(dto, page);
    }
}